{$R-}

(*
	recvUpTo(port number, termination character, waitTime, echo, edit) -- Return a string from the
		serial port; return everything available, up to the termination character (if any). Pass an empty
		termination character to receive everything available. WaitTime is the amount of time to wait
		for the input, in ticks (60ths of a second). Echo is true to enable echoing. Edit is
		true to enable edit characters (i.e., backspace).

	To compile and link this file using Macintosh Programmer's Workshop,

	pascal -w recvUpTo.p
	link -m ENTRYPOINT -o HyperCommands -rt XFCN=0 -sn Main=recvUpTo recvUpTo.p.o "{MPW}"Libraries:interface.o
	
*)

{$S recvUpTo } 	{ Segment name must be the same as the command name. }

unit DummyUnit;

interface

uses MemTypes, QuickDraw, OSIntf, ToolIntf, HyperXCmd;

procedure EntryPoint(paramPtr: XCmdPtr);
	
implementation

const

return = chr(13);
linefeed = chr(10);
bs = chr(8);

type

Str31 = String[31];

procedure recvUpTo(paramPtr: XCmdPtr); forward;

procedure EntryPoint(paramPtr: XCmdPtr);

	begin
		recvUpTo(paramPtr);
	end;

procedure recvUpTo(paramPtr: XCmdPtr);

	var portNumber: integer;
		inPort, outPort: integer;
		str: Str255;
		l: longInt;
		waitForChars: longInt;
		lookForTerm: boolean;
		termChar: char;
		echoOn: boolean;
		editOn: boolean;
		linefeedStr: string[1];
		bsStr: string[3];

	{$I XCmdGlue.inc}

	procedure Fail(errMsg: Str255); { set theResult and quit }
		begin
			paramPtr^.returnValue := PasToZero(errMsg);
			exit(recvUpTo);
		end;

	begin
		if paramPtr^.paramCount <> 5 then Fail('parameter count is not 5');

		ZeroToPas(paramPtr^.params[1]^,str);		{ First parameter is port number. }
		portNumber := StrToNum(str);
		if (portNumber < 1) or (portNumber > 2) then Fail('invalid port number');
		ZeroToPas(paramPtr^.params[2]^,str);		{ Second parameter is termination character. }
		if length(str) = 0 then lookForTerm := false
		else
			begin
				lookForTerm := true;
				termChar := str[1];
			end;
		ZeroToPas(paramPtr^.params[3]^,str);		{ Third parameter is whether to wait. }
		waitForChars := StrToNum(str);
		ZeroToPas(paramPtr^.params[4]^,str);		{ Fourth parameter is whether to echo. }
		echoOn := false;
		if length(str) > 0 then
			if (str[1] = 't') or (str[1] = 'T') then echoOn := true;
		ZeroToPas(paramPtr^.params[5]^,str);		{ Fifth parameter is whether to edit. }
		editOn := false;
		if length(str) > 0 then
			if (str[1] = 't') or (str[1] = 'T') then editOn := true;

		if portNumber = 1 then
			begin
				inPort := -6;
				outPort := -7;
			end
		else
			begin
				inPort := -8;
				outPort := -9;
			end;
		linefeedStr[0] := chr(1); linefeedStr[1] := linefeed;
		bsStr := '   '; bsStr[1] := bs; bsStr[3] := bs;
		str := '';
		waitForChars := waitForChars + TickCount;
		while TickCount <= waitForChars do
			begin
				if SerGetBuf(inPort,l) <> noErr then Fail('SerGetBuf failed');
				if l = 0 then cycle;
				str[0] := chr(integer(str[0])+1);
				l := 1;
				if FSRead(inPort,l,Ptr(ord4(@str)+ord(str[0]))) <> noErr then Fail('FSRead failed');
				if echoOn then
					begin
						l := 1;
						if FSWrite(outPort,l,Ptr(ord4(@str)+ord(str[0]))) <> noErr then Fail('FSWriter failed');
						if str[length(str)] = return then
							begin
								l := length(linefeedStr);
								if FSWrite(outPort,l,Ptr(ord4(@linefeedStr)+1)) <> noErr then Fail('FSWrite failed');
							end;
						if editOn and (str[length(str)] = bs) then
							begin
								l := length(bsStr);
								if FSWrite(outPort,l,Ptr(ord4(@bsStr)+1)) <> noErr then Fail('FSWrite failed');
							end;
					end;
				if editOn then
					begin
						if str[length(str)] = bs then
							begin
								str[0] := chr(length(str)-1);
								if length(str) > 0 then str[0] := chr(length(str)-1);
							end;
					end;
				if lookForTerm then
					if str[length(str)] = termChar then leave;
				if length(str) = 255 then leave;
			end;
		paramPtr^.returnValue := PasToZero(str);
	end;

end.
